﻿using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;

namespace MedianSocketService.netty.HighPowerProtocol
{
    public class HighPowerDecoder : ByteToMessageDecoder
    {
        // 包头长度
        private const int HeaderLength = 14;
        // 包尾长度
        private const int FooterLength = 2;
        protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
        {
            try
            {
                while (true)
                {
                    // 标记当前读取位置
                    input.MarkReaderIndex();
                    // 可读取的字节数
                    int readableBytes = input.ReadableBytes;
                    // 如果数据不足一个完整的包头，直接返回
                    if (readableBytes < HeaderLength + FooterLength)
                    {
                        break;
                    }
                    // 读取包头
                    byte[] header = new byte[HeaderLength];
                    input.ReadBytes(header);

                    // 检查包头是否合法
                    if (!IsValidHeader(header))
                    {
                        // 恢复之前的读取位置
                        input.ResetReaderIndex();
                        input.ReadByte();
                        continue;
                    }
                    // 读取包体+包尾长度
                    int bodyLength = (0xff00 & header[13] << 8 | 0xff & header[12]);
                    // 如果可读取的字节数小于数据体长度加包尾长度，说明数据不足一个完整的包，直接返回
                    if (readableBytes < HeaderLength + bodyLength)
                    {
                        // 恢复之前的读取位置
                        input.ResetReaderIndex();
                        return;
                    }
                    // 读取包体+包尾
                    byte[] bodyAndTail = new byte[bodyLength];
                    input.ReadBytes(bodyAndTail);
                    var sendByte = header.Concat(bodyAndTail).ToArray();
                    var hexStr = this.ByteToHexStr(sendByte);
                    // 将解码后的消息添加到 output 列表中，交给后面的处理器进行处理
                    output.Add(sendByte);
                }
            }
            catch (Exception ex)
            {
                // 发生异常时，抛出 CorruptedFrameException 异常，表示解码出错
                throw new CorruptedFrameException("Decode error!");
            }
        }
        /// <summary>
        /// 检查包头是否合法
        /// </summary>
        /// <param name="header"></param>
        /// <returns></returns>
        private bool IsValidHeader(byte[] header)
        {
            if (header.Length != HeaderLength)
            {
                return false;
            }
            return header[0] == 0xFF && header[1] == 0xAA && header[2] == 0x55 && header[3] == 0xFF;
        }
        /// <summary>
        /// 检查包尾是否合法
        /// </summary>
        /// <param name="footer"></param>
        /// <returns></returns>
        private bool IsValidFooter(byte[] footer)
        {
            if (footer.Length != FooterLength)
            {
                return false;
            }
            return footer[0] == 0xFE && footer[1] == 0xFE;
        }


        #region __十六进制字符串转字节型__
        /// <summary>
        /// 字符串转16进制字节数组(方法2)
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public byte[] StrToToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = System.Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }
        #endregion

        #region __字节型转十六进制字符串__
        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public string ByteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2") + " ";
                }
            }
            return returnStr;
        }
        #endregion
    }
}